<!--
 * @Description: home页面
 * @Version: 2.0
 * @Date: 2024-04-09 11:46:34
 * @LastEditTime: 2024-05-17 17:07:44
-->
<template>
  <el-container class="container_cover">
    <el-container class="container_center">
      <!-- 左侧导航菜单 -->
      <el-aside :width="asideWidth" v-if="!isMobile()"> <Aside /> </el-aside>

      <!-- 右侧主体 -->
      <el-container class="container_right">
        <el-icon
          v-if="isMobile()"
          style="margin: 6px; z-index: 99"
          size="20"
          @click="handleDrawer"
          ><Expand
        /></el-icon>
        <!-- 展开收缩图标 -->
        <el-icon
          v-else
          size="20"
          color="#414346"
          @click="onFlod"
          class="icon_style"
        >
          <component :is="collapse ? ArrowRight : ArrowLeft"></component>
        </el-icon>
        <!-- chat主体部分 -->
        <el-container class="chatview" ref="chatMessages">
          <!-- GPT 的回复 -->
          <div
            v-for="(message, index) in data.messages"
            :key="index"
            :class="{
              'gpt-message': message.type === accountType.GPT,
              'user-message': message.type === accountType.USER,
            }"
          >
            <div v-if="message.type === accountType.GPT">
              <div class="gpt_head">
                <el-avatar :src="message.avatar" size="default"></el-avatar>
                <span style="margin-left: 10px">{{ Var.PROJECT_NAME }}</span>
              </div>
              <el-tooltip :content="message.text" placement="top">
                <div
                  class="message-text"
                  :class="{ 'code-message': message.isCode }"
                >
                  {{ message.text }}
                </div>
              </el-tooltip>
            </div>
            <template v-else>
              <div class="user_head">
                <span style="margin-right: 10px">{{
                  store?.accountInfo?.nickname
                }}</span>
                <el-avatar :src="message.avatar" size="default"></el-avatar>
              </div>
              <el-tooltip :content="message.text" placement="top">
                <div class="message-text">{{ message.text }}</div>
              </el-tooltip>
            </template>
          </div>
          <div ref="lastMessage"></div>
        </el-container>
        <!-- footer -->
        <div class="sengChat">
          <el-popconfirm
            width="200"
            confirm-button-text="是"
            cancel-button-text="否"
            title="确认清空对话内容吗 ?"
            @confirm="confirmEvent"
          >
            <template #reference>
              <el-icon size="20" class="delete_icon"><Delete /></el-icon>
            </template>
          </el-popconfirm>

          <el-input
            v-model="chatValue.question"
            autocomplete="off"
            placeholder="想问我什么呢 ？"
            @keyup.enter="debouncedConfirmEvent"
          />
          <el-button
            v-if="!stopStatus"
            type="warning"
            @click="cancelRequest"
            :disabled="stopStatus"
          >
            终止
          </el-button>
          <el-button
            :disabled="chatStatus.btnDisabled"
            type="success"
            @click="debouncedConfirmEvent"
            :loading="chatStatus.loading"
          >
            <el-icon size="25" color="#fff"><Promotion /></el-icon>
          </el-button>
        </div>
      </el-container>
    </el-container>
    <el-drawer
      size="80%"
      v-model="leftdrawer"
      :title="store?.accountInfo?.nickname"
      direction="ltr"
    >
      <span>待开发...</span>
    </el-drawer>
  </el-container>
</template>
<script setup lang="ts">
import { IStore } from "@/App.vue";
import { QueryApi } from "@/api/api";
import { accountType } from "@/config/Enum";
import Var from "@/config/Var";
import { useDebounce } from "@/hooks/UseDebounce";
import { isMobile } from "@/utils/index";
import Aside from "@/views/home/Aside.vue";
import {
  ArrowLeft,
  ArrowRight,
  Delete,
  Expand,
  Promotion,
} from "@element-plus/icons-vue";
import { ElMessage, ElLoading } from "element-plus";
import { inject, nextTick, onMounted, reactive, ref, toRefs, watch } from "vue";
import chaticon from "../../../public/images/ChatGPT.svg";

interface messageType {
  isCode: boolean; //是否代码
  isPreview: boolean; //是否gpt回复前的测试
  text: string;
  type: accountType;
  avatar?: string;
}

// 引入全局信息
const store = inject<IStore>("store");
// 引入防抖函数
const { debounce } = useDebounce();

const lastMessage = ref();

const data = reactive<{
  // 左侧输入框收缩控制
  collapse: boolean;
  // 左侧输入框宽
  asideWidth: string;
  // 输入的内容
  chatValue: {
    question: string;
  };
  chatStatus: {
    // 发送按钮状态
    btnDisabled: boolean;
    // 请求状态
    loading: boolean;
  };
  // 对话信息
  messages: messageType[];
  // 手机端左侧抽屉
  leftdrawer: boolean;
  // 请求信号
  controller: AbortController | null;
  // 终止按钮状态
  stopStatus: boolean;
}>({
  collapse: false,
  asideWidth: "",
  chatValue: {
    question: "",
  },
  chatStatus: {
    btnDisabled: true,
    loading: false,
  },
  messages: [
    {
      isCode: false,
      isPreview: false,
      text: "请对我说点什么...",
      type: accountType.GPT,
      avatar: chaticon,
    },
  ],
  leftdrawer: false,
  controller: null,
  stopStatus: true,
});

// 控制aside收缩或展开
const onFlod = () => {
  asideWidth.value = collapse.value ? "260px" : "0";
  collapse.value = !collapse.value;
};

// 确认清空对话内容
const confirmEvent = () => {
  console.log("confirm!");
  data.messages = [
    {
      isCode: false,
      isPreview: false,
      text: "请对我说点什么...",
      type: accountType.GPT,
      avatar: chaticon,
    },
  ];
};

// 点击按钮提问
const handleButtonClick = async () => {
  if (data.chatValue.question.trim() === "") {
    ElMessage.warning("请对我说点什...");
    return;
  }
  data.stopStatus = false;
  // const messageInstance = ElMessage({
  //   message: "思考中...",
  //   type: "info",
  //   duration: 0, // 0表示消息不会自动关闭
  //   showClose: true, // 显示关闭按钮
  // });
  data.controller = new AbortController();
  try {
    data.chatStatus.btnDisabled = false;
    // loading
    data.chatStatus.loading = true;

    // 处理按钮点击事件
    // console.log("Button was clicked!");
    // 这里放置按钮点击后的逻辑
    // 添加用户消息
    data.messages.push({
      isCode: false,
      isPreview: false,
      text: data.chatValue.question,
      type: accountType.USER,
      avatar: store?.accountInfo?.avatar,
    });
    data.chatValue.question = "";
    // 模拟 GPT 回复
    data.messages.push({
      isCode: false,
      isPreview: true,
      text: "加载中...",
      type: accountType.GPT,
      avatar: chaticon,
    });
    scrollToLastMessage(); // 聚焦到最新消息
    const res = await QueryApi.query(
      { question: data.chatValue.question },
      data.controller.signal
    );
    console.log("🚀 ~ handleButtonClick ~ res:", res);
    // 成功后关闭消息
    // messageInstance.close();
    replaceData(res);
    data.chatStatus.btnDisabled = true;
  } catch (error) {
    // 失败时更新消息内容和类型
    // messageInstance.close();
    // 模拟 GPT 回复
    replaceData();
  } finally {
    scrollToLastMessage(); // 聚焦到最新消息
    // loading
    data.chatStatus.loading = false;
    data.stopStatus = true;
  }
};

// 聚焦到最新消息
const scrollToLastMessage = () => {
  nextTick(() => {
    lastMessage.value.scrollIntoView({ behavior: "smooth", block: "end" });
  });
};

// 手机端展示抽屉
const handleDrawer = () => {
  data.leftdrawer = true;
  console.log("data.leftdrawer::: ", data.leftdrawer);
};

// 替换gpt测试数据为真实数据
const replaceData = (res?: string) => {
  // 找出preview的那条数据
  const msgIndex = data.messages.findIndex((item) => item.isPreview === true);

  // 模拟 GPT 回复
  if (msgIndex !== -1 && res) {
    const resData = {
      isCode: false,
      isPreview: false,
      text: res,
      type: accountType.GPT,
      avatar: chaticon,
    };
    // 将preview的那条数据替换为GPT真实的回复
    data.messages.splice(msgIndex, 1, resData);
  } else {
    const errorData = {
      isCode: false,
      isPreview: false,
      text: "Sorry, I am unable to process your Request at the moment.",
      type: accountType.GPT,
      avatar: chaticon,
    };
    // 将preview的那条数据替换为GPT真实的回复
    data.messages.splice(msgIndex, 1, errorData);
  }
};

// 人为终止请求
const cancelRequest = () => {
  if (data.controller) {
    data.controller.abort();
    data.controller = null;
  }
};

const debouncedConfirmEvent = debounce(handleButtonClick, 300);

const { collapse, asideWidth, chatValue, chatStatus, leftdrawer, stopStatus } =
  toRefs(data);

// 监听消息变化，确保每次有新消息时自动聚焦
onMounted(() => {
  if (isMobile()) {
    console.log("手机");
  } else {
    console.log("网页");
  }
  scrollToLastMessage();
});

// 监听输入框数据变化,控制发送按钮状态
watch(
  () => data.chatValue.question,
  (value) => {
    if (value.trim() !== "") {
      data.chatStatus.btnDisabled = false;
    } else {
      data.chatStatus.btnDisabled = true;
    }
  }
);
</script>
<style lang="less" scoped>
.container_cover {
  width: 100%;
  height: 100vh;
  overflow: hidden;
  padding: 16px;
  // border: 1px solid #abc;
  .container_center {
    width: 100%;
    height: 100%;
    border: 1px solid #e5e7eb;
    box-shadow: 1px 1px 3px 2px rgba(0, 0, 0, 0.2);
    border-radius: 10px; /* 设置圆角为 10px */
    overflow: hidden;

    .el-aside {
      transition: width 0.3s; /* 宽度变化过渡效果 */
    }
    .container_right {
      position: relative;
      .icon_style {
        width: 20px;
        height: 20px;
        border-radius: 10px;
        border: 1px solid #abc;
        position: absolute;
        left: -10px;
        top: 50%;
        z-index: 1;
        background-color: #fff;
      }
      .icon_style:hover {
        border: 2px solid #abc;
      }
      .chatview {
        width: 100%;
        height: calc(100% - 72px);
        overflow-y: auto;
        position: absolute;
        left: 0;
        top: 0;
        padding: 16px;
        // border: 1px solid red;
        display: flex;
        flex-direction: column;

        .gpt-message {
          display: flex;
          justify-content: flex-start;
          align-items: center;
          padding: 6px;
          // background-color: #abc;
          margin-bottom: 10px;
          // border: 1px solid red;
          .gpt_head {
            display: flex;
            align-items: center;
            margin-bottom: 10px;
          }
        }

        .user-message {
          display: flex;
          flex-direction: column;
          justify-content: flex-end;
          align-items: flex-end;
          // background-color: whitesmoke;
          margin-bottom: 10px;
          padding: 10px;
          // border: 1px solid red;
          .user_head {
            display: flex;
            align-items: center;
            margin-bottom: 10px;
            // border: 1px solid red;
          }
        }

        .message-text {
          margin-left: 10px;
          margin-right: 10px;
        }
        /* 新增的代码消息样式 */
        .code-message {
          background-color: #000;
          color: #fff;
          padding: 10px;
          border-radius: 5px;
          white-space: pre-wrap;
        }
      }
      .sengChat {
        width: 100%;
        height: 72px;
        position: absolute;
        left: 0;
        bottom: 0;
        padding: 16px;
        // border: 1px solid red;
        display: flex;
        align-items: center;
        justify-content: space-around;
        box-sizing: border-box;
        .delete_icon {
          width: 40px;
          height: 36px;
          cursor: pointer;
          line-height: 36px;
        }
        .delete_icon:hover {
          background-color: #e5e7eb;
          border-radius: 20px;
          box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); /* 设置阴影 */
        }
        .el-input {
          height: 36px;
          margin: 0 12px;
        }
        .el-button {
          height: 36px;
        }
      }
    }
  }
}
</style>
